package com.aaa.ss.util;


import com.aaa.common.constants.BusinessConstant;
import com.aaa.common.util.LoginUserInfo;
import com.aaa.ss.entity.OperLog;
import com.aaa.ss.entity.User;
import com.aaa.ss.service.OperLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;

//使用AOP技术，记录操作日志（项目中对所有表的增删改，都要使用到）
@Component
@Aspect //标记为通知类（增强类） 切面功能的具体实现类
//切面是从业务中独立出的功能
public class OperationLogHandler {

//    //切入点配置
//    @Pointcut("execution(* com.aaa.ss.service.impl.*.*(..))")
//    private void pointA(){
//
//    }

    //
    @Resource
    private OperLogService operLogService;
    @Resource
    private HttpSession httpSession;

    /**
     * 使用后置通知，当业务方法执行完毕时，记录操作日志
     * @param joinPoint
     */
    @AfterReturning(pointcut = "execution(* com.aaa.ss.service.impl.*.insert*(..))" +
            "||execution(* com.aaa.ss.service.impl.*.update*(..))" +
            "||execution(* com.aaa.ss.service.impl.*.delete*(..))")
    public void recordOperationLog(JoinPoint joinPoint){
        OperLog operLog=new OperLog();
        operLog.setTitle("后台管理模块");
        //执行方法的名称
        String methodName = joinPoint.getSignature().getName();
        int businessType= BusinessConstant.OperationLogType.DELETE;
        if (methodName.contains("insert")){
            businessType=BusinessConstant.OperationLogType.INSERT;
        }else if(methodName.contains("update")){
            businessType=BusinessConstant.OperationLogType.UPDATE;
        }
        operLog.setBusinessType(businessType);
        //获取目标对象的名称  含有连接点的对象都是目标对象
        //切入点就是多个链接点的集合 链接点是切入点表达式拦截到的所有业务的执行
        // className = com.aaa.ss.service.impl.MenuServiceImpl...
        String className = joinPoint.getTarget().getClass().getName();
        operLog.setMethod(className+"."+methodName);
        //设置操作类型，1为后台用户，2为手机端用户
        operLog.setOperatorType(1);
        //
        String operName="admin";
        String deptName="开发部";
        LoginUserInfo user=(LoginUserInfo) httpSession.getAttribute("userInfo");
        if(user!=null){
            operName=user.getLoginName();
            deptName=user.getDeptName();
        }
        //获取操作人及部门信息
        operLog.setOperName(operName);
        operLog.setDeptName(deptName);
        //获取Request对象
        ServletRequestAttributes requestAttributes=
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        //获取请求的url
        String operUri=request.getRequestURI();
        operLog.setOperUrl(operUri);
        //设置Ip
        operLog.setOperIp(request.getRemoteAddr());
        //设置位置
        operLog.setOperLocation("内网IP");
        //获取请求参数
        Object[] args = joinPoint.getArgs();// 获取链接点的所有参数
        if(args!=null&&args.length>0){
            //获取第一个参数
            String simpleName = args[0].getClass().getSimpleName();
            operLog.setOperParam(simpleName);
        }
        //设置是否有异常
        operLog.setStatus(0);
        //设置错误信息
        operLog.setErrorMsg("无异常");
        //设置操作时间
        operLog.setOperTime(new Date());
        operLogService.insert(operLog);
    }
    //@AfterThrowing(pointcut = "pointA()" , throwing = "ex")
    public void afterException(JoinPoint joinPoint, Exception ex){
        OperLog operLog = new OperLog() ;
        //同上
        //设置是否有异常
        operLog.setStatus(1);
        operLog.setErrorMsg( ex . getClass() . getName());
        operLogService . insert(operLog);
    }

}
